#ifndef EVENTLOOP_CHANNEL
#define EVNETLOOP_CHNNAEL

#include "utility/Noncopyable.h"
#include "utility/chrono.h"
#include <memory>
#include <poll.h>

class Eventloop;

class Channel
{
public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Utility::timepoint)>;

    Channel(Eventloop *loop, int fd);
    ~Channel();

    void handle_event(Utility::timepoint recvTime);
    void set_read_callback(const ReadEventCallback &cb) { _readCallback = cb; }
    void set_write_callback(const EventCallback &cb) { _writeCallback = cb; }

    // tie this channel to the owner object managed by shared_ptr
    // prevent the owner object being destroyed in handle_event
    void tie(std::shared_ptr<void> &);

    
    void remove();

    int fd() const { return _fd; };
    int events() const { return _events; }
    void set_revents(int revent) { _revents = revent; }
    bool is_non_event() const { return _events == kNoneEvent; }

    void enable_reading() { _events |= kReadEvent; _update(); }
    void enable_writing() { _events |= kWriteEvent; _update(); }
    void disable_writing() { _events &= ~kWriteEvent; _update(); }
    bool is_writing() const { return _events & kWriteEvent; }
    
    // for Poller
    int index() const { return _index; }
    void set_index(int index) { _index = index; }

    void do_not_LogHup() { _logHup = false; }

    Eventloop *owner_loop() { return _loop; }

    // for debug
    std::string revents_to_string() const;

private:
    NONCOPYABLE(Channel);

    void _update();
    void _handle_event_with_guard(Utility::timepoint recvTime);

    inline static const int kNoneEvent = 0;
    inline static const int kReadEvent = POLLIN | POLLPRI;
    inline static const int kWriteEvent = POLLOUT;

    Eventloop *_loop;   // loop that owns this channel
    const int _fd;      // file decriptor for this channel manages(not own)
    int _events;        // events in listening
    int _revents;       // returned events from poll/epoll
    int _index;         // index in the event array of poll
    int _logHup;        // for POLLUP

    std::weak_ptr<void> _tie;
    bool _tied;
    bool _eventHandling;
    ReadEventCallback _readCallback;
    EventCallback     _writeCallback;
    EventCallback     _closeCallback;
    EventCallback     _errorCallback;
};



#endif